[HVM] Fix oprofile for HVM guests.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 20 Oct 2006 09:34:24 +0000 (10:34 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 20 Oct 2006 09:34:24 +0000 (10:34 +0100)
Signed-off-by: Tom Woller <thomas.woller@amd.com>
Signed-off-by: Mats Petersson <mats.petersson@amd.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/hvm/svm/x86_32/exits.S
xen/arch/x86/hvm/svm/x86_64/exits.S
xen/arch/x86/oprofile/op_model_athlon.c
xen/arch/x86/oprofile/op_model_p4.c
xen/arch/x86/oprofile/op_model_ppro.c
xen/arch/x86/oprofile/xenoprof.c

index 99a08cd483d2fdb59b85ab10d62fb06071129bd1..a2714030fd07bc219072f9df162af3d16e1eb9ce 100644 (file)
@@ -126,6 +126,8 @@ ENTRY(svm_asm_do_launch)
 
         HVM_SAVE_ALL_NOSEGREGS
         STGI
+.globl svm_stgi_label;
+svm_stgi_label:
         movl %esp,%eax
         push %eax
         call svm_vmexit_handler
index 1e36baf53d164c6f779fd4cbf202654ed0f9d6a3..11c62f9d9e2c61d6d3446bafe84ce9d98b2a9edb 100644 (file)
@@ -144,6 +144,8 @@ ENTRY(svm_asm_do_launch)
         VMLOAD
 
         STGI
+.globl svm_stgi_label;
+svm_stgi_label:
         movq %rsp,%rdi
         call svm_vmexit_handler
         jmp  svm_asm_do_resume
index c946c1ea8eb8134e7eb41fc7e51a51f4d5f0fefb..1d8f9668f468a883db42257456ba77f2cc8ebc7b 100644 (file)
@@ -18,6 +18,7 @@
 #include <xen/sched.h>
 #include <asm/regs.h>
 #include <asm/current.h>
+#include <asm/hvm/support.h>
  
 #include "op_x86_model.h"
 #include "op_counter.h"
@@ -44,7 +45,11 @@ static unsigned long reset_value[NUM_COUNTERS];
 
 extern void xenoprof_log_event(struct vcpu *v, unsigned long eip,
                               int mode, int event);
+extern int xenoprofile_get_mode(struct vcpu *v,
+                               struct cpu_user_regs * const regs);
+
+extern char svm_stgi_label[];
+
 static void athlon_fill_in_addresses(struct op_msrs * const msrs)
 {
        msrs->counters[0].addr = MSR_K7_PERFCTR0;
@@ -97,10 +102,9 @@ static void athlon_setup_ctrs(struct op_msrs const * const msrs)
        }
 }
 
 static int athlon_check_ctrs(unsigned int const cpu,
-                             struct op_msrs const * const msrs,
-                             struct cpu_user_regs * const regs)
+                            struct op_msrs const * const msrs,
+                            struct cpu_user_regs * const regs)
 
 {
        unsigned int low, high;
@@ -108,11 +112,19 @@ static int athlon_check_ctrs(unsigned int const cpu,
        int ovf = 0;
        unsigned long eip = regs->eip;
        int mode = 0;
-
-       if (guest_kernel_mode(current, regs))
-               mode = 1;
-       else if (ring_0(regs))
-               mode = 2;
+       struct vcpu *v = current;
+       struct cpu_user_regs tmp_regs;
+
+       if (!guest_mode(regs) &&
+           (regs->eip == (unsigned long)svm_stgi_label)) {
+               /* SVM guest was running when NMI occurred */
+               hvm_store_cpu_guest_regs(v, &tmp_regs, NULL);
+               eip = tmp_regs.eip;
+               mode = xenoprofile_get_mode(v, &tmp_regs);
+       } else {
+               eip = regs->eip;
+               mode = xenoprofile_get_mode(v, regs);
+       }
 
        for (i = 0 ; i < NUM_COUNTERS; ++i) {
                CTR_READ(low, high, msrs, i);
index 018124eaf9ef15af2f1a8bd50da2f68339294060..c285ea1d41518d1393b5efa67a81357b51a33624 100644 (file)
@@ -620,9 +620,10 @@ static void p4_setup_ctrs(struct op_msrs const * const msrs)
        }
 }
 
-
 extern void xenoprof_log_event(struct vcpu *v, unsigned long eip,
                               int mode, int event);
+extern int xenoprofile_get_mode(struct vcpu *v,
+                               struct cpu_user_regs * const regs);
 
 static int p4_check_ctrs(unsigned int const cpu,
                          struct op_msrs const * const msrs,
@@ -632,12 +633,7 @@ static int p4_check_ctrs(unsigned int const cpu,
        int i;
        int ovf = 0;
        unsigned long eip = regs->eip;
-       int mode = 0;
-
-       if (guest_kernel_mode(current, regs))
-               mode = 1;
-       else if (ring_0(regs))
-               mode = 2;
+       int mode = xenoprofile_get_mode(current, regs);
 
        stag = get_stagger();
 
index b982443928ee1adc3217ec53a4b4b9c88353f91c..139f4571bf8ffb5d50b0dec5847aeb80f4a3fa95 100644 (file)
@@ -88,9 +88,10 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs)
        }
 }
 
-
 extern void xenoprof_log_event(struct vcpu *v, unsigned long eip,
                               int mode, int event);
+extern int xenoprofile_get_mode(struct vcpu *v,
+                               struct cpu_user_regs * const regs);
  
 static int ppro_check_ctrs(unsigned int const cpu,
                            struct op_msrs const * const msrs,
@@ -100,13 +101,8 @@ static int ppro_check_ctrs(unsigned int const cpu,
        int i;
        int ovf = 0;
        unsigned long eip = regs->eip;
-       int mode = 0;
+       int mode = xenoprofile_get_mode(current, regs);
 
-       if ( guest_kernel_mode(current, regs) ) 
-               mode = 1;
-       else if ( ring_0(regs) )
-               mode = 2;
        for (i = 0 ; i < NUM_COUNTERS; ++i) {
                CTR_READ(low, high, msrs, i);
                if (CTR_OVERFLOWED(low)) {
index f60656ba8cd9f05a7e63ac31af9dac8a4302f069..27c2a90297891049ae9826d123bd00ac7ed0158c 100644 (file)
@@ -7,6 +7,7 @@
 #include <xen/guest_access.h>
 #include <xen/sched.h>
 #include <public/xenoprof.h>
+#include <asm/hvm/support.h>
 
 #include "op_counter.h"
 
@@ -98,7 +99,7 @@ static void xenoprof_reset_buf(struct domain *d)
     }
 }
 
-char *alloc_xenoprof_buf(struct domain *d, int npages)
+static char *alloc_xenoprof_buf(struct domain *d, int npages)
 {
     char *rawbuf;
     int i, order;
@@ -121,7 +122,8 @@ char *alloc_xenoprof_buf(struct domain *d, int npages)
     return rawbuf;
 }
 
-int alloc_xenoprof_struct(struct domain *d, int max_samples, int is_passive)
+static int alloc_xenoprof_struct(
+    struct domain *d, int max_samples, int is_passive)
 {
     struct vcpu *v;
     int nvcpu, npages, bufsize, max_bufsize;
@@ -207,7 +209,7 @@ void free_xenoprof_pages(struct domain *d)
     d->xenoprof = NULL;
 }
 
-int active_index(struct domain *d)
+static int active_index(struct domain *d)
 {
     int i;
 
@@ -218,7 +220,7 @@ int active_index(struct domain *d)
     return -1;
 }
 
-int set_active(struct domain *d)
+static int set_active(struct domain *d)
 {
     int ind;
     struct xenoprof *x;
@@ -239,7 +241,7 @@ int set_active(struct domain *d)
     return 0;
 }
 
-int reset_active(struct domain *d)
+static int reset_active(struct domain *d)
 {
     int ind;
     struct xenoprof *x;
@@ -265,7 +267,7 @@ int reset_active(struct domain *d)
     return 0;
 }
 
-void reset_passive(struct domain *d)
+static void reset_passive(struct domain *d)
 {
     struct xenoprof *x;
 
@@ -281,7 +283,7 @@ void reset_passive(struct domain *d)
     return;
 }
 
-void reset_active_list(void)
+static void reset_active_list(void)
 {
     int i;
 
@@ -297,7 +299,7 @@ void reset_active_list(void)
     activated = 0;
 }
 
-void reset_passive_list(void)
+static void reset_passive_list(void)
 {
     int i;
 
@@ -311,7 +313,7 @@ void reset_passive_list(void)
     pdomains = 0;
 }
 
-int add_active_list (domid_t domid)
+static int add_active_list(domid_t domid)
 {
     struct domain *d;
 
@@ -329,7 +331,7 @@ int add_active_list (domid_t domid)
     return 0;
 }
 
-int add_passive_list(XEN_GUEST_HANDLE(void) arg)
+static int add_passive_list(XEN_GUEST_HANDLE(void) arg)
 {
     struct xenoprof_passive passive;
     struct domain *d;
@@ -436,7 +438,7 @@ void xenoprof_log_event(
     }
 }
 
-int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg)
+static int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg)
 {
     struct xenoprof_init xenoprof_init;
     int ret;
@@ -458,7 +460,7 @@ int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg)
     return 0;
 }
 
-int xenoprof_op_get_buffer(XEN_GUEST_HANDLE(void) arg)
+static int xenoprof_op_get_buffer(XEN_GUEST_HANDLE(void) arg)
 {
     struct xenoprof_get_buffer xenoprof_get_buffer;
     struct domain *d = current->domain;
@@ -694,6 +696,17 @@ int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg)
     return ret;
 }
 
+int xenoprofile_get_mode(struct vcpu *v, struct cpu_user_regs * const regs)
+{
+    if ( !guest_mode(regs) )
+        return 2;
+
+    if ( hvm_guest(v) )
+        return ((regs->cs & 3) != 3);
+
+    return guest_kernel_mode(v, regs);  
+}
+
 /*
  * Local variables:
  * mode: C